package vek.controllers.SearchAndList;

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import vek.GUI.SearchAndListView.NavigationPanel;
import vek.GUI.SearchAndListView.KeyboardView;
import vek.ObjectDatabase.DatabaseConnector;
import vek.ObjectDatabase.Search;
import vek.Objects.POI;
import javax.swing.JSpinner;
import vek.TerminalSettings;

/**
 * This controller takes care of the user input from the NavigationPanel, but also takes care of access to the Datbase connector
 * and gets the searches from the databases.
 * @author Christian, Michal og Jakob (Hold 1, gruppe 2)
 */
public class NavigationPanelController implements ActionListener, ChangeListener{
    
    private DatabaseConnector databaseConnector;
    private RightPanelViewController rightPanelController;
    private NavigationPanel navigationPanel;
    private KeyboardView keyboardView;
    private Search currentSearch;
    
    /**
     * 
     * @param dbc the database connector which provides access to the databases
     * @param rpc the RightPanelViewController which controls the RightPanelView
     * @param np the NavigationPanel which is the view to this controller
     */
    
    public NavigationPanelController(DatabaseConnector dbc, RightPanelViewController rpc, NavigationPanel np)
    {
        databaseConnector = dbc;
        rightPanelController = rpc;
        navigationPanel = np;
        currentSearch = new Search();
    }
    
    /**
     * Sets the KeyboardView for this controller
     * @param kv the KeyboardView for this controller
     */
    
    public void setKeyboardView(KeyboardView kv)
    {
        keyboardView = kv;
    }
    
    /**
     * Gets the current search. This is the search object which is fowarded to the databases and is used to search for POIs.
     * @return the current search object
     */
    
    public Search getCurrentSearch()
    {
        return currentSearch;
    }
    
    /**
     * Method that runs each time user input occurs.
     * This method hides this panel and shows the on-screen keyboard panel if needed.
     * @param e the ActionEvent which is created when user input occurs
     */

    public void actionPerformed(ActionEvent e) {
        
        
        JComponent source = (JComponent) e.getSource();
        
        if( source.getName().startsWith("menuitem") )
        {
            JMenuItem source2 = (JMenuItem) source;
            
            String[] arg = { source2.getText() };
            currentSearch.removeLastSearchOfType(Search.SearchType.TYPEEQUALS);
            currentSearch.addSearch(Search.SearchType.TYPEEQUALS, arg );
            showInRightPanelFromSearch(currentSearch);
            
        }
        
        if( source.getName().equalsIgnoreCase("findvianame") )
        {
            navigationPanel.hidePanel();
            
            keyboardView.showKeyboard(Search.SearchType.NAMESTARTSWITH);
        }
        else if( source.getName().equalsIgnoreCase("findviatype") )
        {
            navigationPanel.loadAndShowTypePopup(source, databaseConnector.getAllTypes());

        }
        else if( source.getName().equalsIgnoreCase("findviaphonenumber") )
        {

            navigationPanel.hidePanel();
            
            keyboardView.showKeyboard(Search.SearchType.PHONENUMBERSTARTSWITH);
             
        }
        else if( source.getName().equalsIgnoreCase("findviaroad") )
        {
            navigationPanel.hidePanel();
            
            keyboardView.showKeyboard(Search.SearchType.ROADSTARTSWITH);         
        }
        
        else if( source.getName().equalsIgnoreCase("newsearch") )
        {
            newSearch();
            
        }
        else if( source.getName().equalsIgnoreCase("hastoilets") )
        {
            JCheckBox source2 = (JCheckBox) source;
            if( source2.isSelected())
            {
                String[] arg = { "ja" };
                currentSearch.addSearch(Search.SearchType.HASTOILETS, arg);
                showInRightPanelFromSearch(currentSearch);
            }
            else
            {
                currentSearch.removeLastSearchOfType(Search.SearchType.HASTOILETS);
                showInRightPanelFromSearch(currentSearch);
            }
        }
        else if( source.getName().equalsIgnoreCase("haselevators") )
        {
            JCheckBox source2 = (JCheckBox) source;
            if( source2.isSelected())
            {
                String[] arg = { "ja" };
                currentSearch.addSearch(Search.SearchType.HASELEVATORS, arg );
                showInRightPanelFromSearch(currentSearch);
            }
            else
            {
                currentSearch.removeLastSearchOfType(Search.SearchType.HASELEVATORS);
                showInRightPanelFromSearch(currentSearch);
            }          
        }
        
        

    }
    
    /**
     * Shows the NavigationPanel, the panel with the search functions.
     */
    
    public void showNavigationPanel()
    {
        navigationPanel.showPanel();
    }
    /**
     * Shows a search in the right panel.
     * The POIs get converted to Strings using the getPOIShortStringRepresentation method and loaded into
     * the right panel using the loadListOfPOIs method.
     * @param search
     */

    
    public void showInRightPanelFromSearch(Search search)
    {
        ArrayList<POI> pois = databaseConnector.searchFor(search);
        ArrayList<ArrayList> poiShortStringRepsAndLocations = new ArrayList<ArrayList>();
        ArrayList<Point> poiLocations = getPOILocations(pois);
        ArrayList<String> poiShortStringReps = getPOIShortStringRepresentation ( pois );
        poiShortStringRepsAndLocations.add(poiShortStringReps);
        poiShortStringRepsAndLocations.add(poiLocations);
        rightPanelController.loadListOfPOIs( poiShortStringRepsAndLocations );
        navigationPanel.setTextOnCurrentSearchingLabel(search.toStringFancy());
    }
    
    /**
     * Gets the location of all the specified POIs.
     * The location is the POIs point on the map, that is its x and y coordinates.
     * @see Point
     * @param pois the POIs which location is to be found
     * @return an ArrayList of Points, where each Point contains an X and a Y coordinate
     */
    
    private ArrayList<Point> getPOILocations(ArrayList<POI> pois)
    {
        ArrayList<Point> poiLocations = new ArrayList<Point>();
        for(int i = 0; i < pois.size(); i++)
        {
            poiLocations.add( pois.get(i).getLocation() );
        }
        return poiLocations;
    }
    
    /**
     * Gets the POIs string representation which is fit to be displayed in the right panel.
     * The method toListString is used for this purpose.
     * @param pois the POIs which should be shown in the right panel.
     * @return an ArrayList containing each POIs string representation.
     */
    
    private ArrayList<String> getPOIShortStringRepresentation(ArrayList<POI> pois)
    {
        ArrayList<String> poiShortStringReps = new ArrayList<String>();
        
        for(int i = 0; i < pois.size(); i++)
        {
            poiShortStringReps.add( pois.get(i).toListString() );
        }
        return poiShortStringReps;
    }
    
    /**
     * Starts a new Search.
     * Resets the GUI and creates a new Search object.
     */
    
    private void newSearch()
    {
        navigationPanel.getWithXMetersSpinner().setValue(new Double(0));
        rightPanelController.clearListOfPOIs();
        currentSearch = new Search();
        navigationPanel.gethasToiletsCheckBox().setSelected(false);
        navigationPanel.setTextOnCurrentSearchingLabel("");
    }
    
    /**
     * This method is run each time the JSpinner is used.
     * @see JSpinner
     * @param e the ChangeEvent which occurs when the user interacts with the JSpinner.
     */
    
    public void stateChanged(ChangeEvent e) {
        
        if(currentSearch.containsSearchType(Search.SearchType.ISWITHXMETERS))
        {
            currentSearch.removeLastSearchOfType(Search.SearchType.ISWITHXMETERS);
        }
        
        System.out.println("pixels per meter: " + TerminalSettings.getPixelsPerMeter());
        
        String circleWidthAndHeight = String.valueOf(navigationPanel.getCurrentValueInWithInXMetersSpinner());
        int circleTopLeftCornerXCoord = (int) (TerminalSettings.getTerminalXCoord() - ((
                navigationPanel.getCurrentValueInWithInXMetersSpinner() * TerminalSettings.getPixelsPerMeter()) / 2));
        int circleTopLeftCornerYCoord = (int) (TerminalSettings.getTerminalYCoord() - ((
                navigationPanel.getCurrentValueInWithInXMetersSpinner() * TerminalSettings.getPixelsPerMeter()) / 2));
        
        //System.out.println("circleTopLeftCornerXCoord " + circleTopLeftCornerXCoord + " size: " + circleWidthAndHeight );
        //System.out.println("circleTopLeftCornerYCoord " + circleTopLeftCornerYCoord);
        
        
        String[] arg = { String.valueOf(circleTopLeftCornerXCoord), String.valueOf(circleTopLeftCornerYCoord), circleWidthAndHeight, circleWidthAndHeight };
        currentSearch.addSearch(Search.SearchType.ISWITHXMETERS, arg);
        showInRightPanelFromSearch(currentSearch);
        
        
    }



    
    

}
